﻿namespace ChinaUnicom.ViewModels
{
    using Avatar;
    using Avatar.Commands;
    using Avatar.Log;
    using Avatar.Schedule;
    using ChinaUnicom.Tasks;
    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;

    public class SigningContext : PageContext, INotifyPropertyChanged
    {
        ITaskScheduler taskScheduler;
        string mobile, password, imgCode;

        public SigningContext(string mobile, string password, string imgCode)
        {
            this.mobile = mobile;
            this.password = password;
            this.imgCode = imgCode;

            taskScheduler = SchedulerFactory.Create(SchedulerType.Serial);
            taskScheduler.Error += OnFailed;
            taskScheduler.StateChanged += OnTaskSchedulerStateChanged;

            IsIndeterminate = true;
            tips = "正在登录中，这可能需要等待一段时间，请耐心等待！";
            tipsForeground = Application.Current.Resources["PhoneAccentBrush"] as SolidColorBrush;
            cancelOrContinueText = "取消";

            taskScheduler.Schedule(LoginTask());
            taskScheduler.Schedule(ClientTask());
            taskScheduler.Schedule(FeeTask());
            taskScheduler.Schedule(PackageTask());
            taskScheduler.Schedule(PointTask());
            taskScheduler.Schedule(GenerateProductTask());
        }

        #region Tasks

        ITask LoginTask()
        {
            ITask task = new LoginTask(mobile, password, imgCode);
            task.Completed += OnLoginTaskCompleted;
            task.Failed += OnFailed;

            return task;
        }

        ITask ClientTask()
        {
            ITask task = new ClientTask();
            task.Completed += OnInitializeTaskCompleted;
            task.Failed += OnFailed;

            return task;
        }

        ITask FeeTask()
        {
            ITask task = new FeeTask();
            task.Completed += OnInitializeTaskCompleted;
            task.Failed += OnFailed;

            return task;
        }

        ITask PackageTask()
        {
            ITask task = new PackageTask();
            task.Completed += OnInitializeTaskCompleted;
            task.Failed += OnFailed;

            return task;
        }

        ITask PointTask()
        {
            ITask task = new PointTask();
            task.Completed += OnInitializeTaskCompleted;
            task.Failed += OnFailed;

            return task;
        }

        ITask GenerateProductTask()
        {
            ITask task = new ProductTask();
            task.Failed += OnFailed;
            task.Completed += OnInitializeTaskCompleted;

            return task;
        }

        void OnLoginTaskCompleted(object sender, EventArgs e)
        {
            //SigninTask task = sender as SigninTask;
            Action loginTaskCompletedAction = () =>
            {
                if (taskScheduler.Canceled)
                {
                    TipsForeground = new SolidColorBrush(Colors.White);
                    Tips = "已被取消！";
                }
                else
                {
                    TipsForeground = new SolidColorBrush(Colors.Green);
                    Tips = "登录成功！正在初始化应用程序... 请耐心等待！";
                }
            };

            loginTaskCompletedAction.UIThreadInvoke();
        }

        void OnInitializeTaskCompleted(object sender, EventArgs e)
        {
            Context context = Context.Current;

            string name = sender.GetType().Name.ToLower();
            switch (name)
            {
                case "clienttask":
                    ClientTask clienttask = sender as ClientTask;
                    context.Client = clienttask.Client;
                    context.Account.ClientName = context.Client.Name;
                    break;

                case "feetask":
                    FeeTask feetask = sender as FeeTask;
                    context.Fee = feetask.Fee;
                    break;

                case "packagetask":
                    PackageTask packagetask = sender as PackageTask;
                    context.Package = packagetask.Package;
                    break;

                case "pointtask":
                    PointTask pointtask = sender as PointTask;
                    context.Point = pointtask.Point;
                    break;

                case "producttask":
                    ProductTask producttask = sender as ProductTask;
                    context.Product = producttask.Product;
                    break;
            }

            if (!taskScheduler.Canceled)
            {
                Action action = () =>
                {
                    TipsForeground = new SolidColorBrush(Colors.Green);
                    Tips = "登录成功！正在初始化应用程序... 请耐心等待！";
                };

                action.UIThreadInvoke();
            }
        }

        void OnFailed(object sender, FailedEventArgs e)
        {
            // clear up the local data.
            Authentication.Current.Logout(false);

            Action taskFailedAction = () =>
            {
                (RetryCommand as Command).IsEnabled = true;
                (CancelOrContinueCommand as Command).IsEnabled = false;
                IsIndeterminate = false;
                TipsForeground = new SolidColorBrush(Colors.Red);
                Tips = e.Exception.Message;
            };

            taskFailedAction.UIThreadInvoke();
        }

        void OnTaskSchedulerStateChanged(object sender, StateChangedArgs e)
        {
            if (e.State == ScheduleState.Done)
            {
                Action goBackAction = () =>
                {
                    // remove the login page.
                    Root.RemoveBackEntry();
                    GoBack();
                };

                goBackAction.UIThreadInvoke();
            }
            else if (e.State == ScheduleState.Canceled)
            {
                TipsForeground = new SolidColorBrush(Colors.White);
                Tips = "已被取消！";
            }
        }

        #endregion

        #region ICommands

        Command retryCommand;
        public ICommand RetryCommand
        {
            get
            {
                if (retryCommand == null)
                {
                    retryCommand = new Command(param =>
                    {
                        taskScheduler.Canceled = false;
                        GoBack();
                    });

                    retryCommand.IsEnabled = false;
                }

                return retryCommand;
            }
        }

        Command cancelOrContinueCommand;
        public ICommand CancelOrContinueCommand
        {
            get
            {
                if (cancelOrContinueCommand == null)
                {
                    cancelOrContinueCommand = new Command(param =>
                    {
                        if (param != null && param.Equals("OnBackKeyPress"))
                        {
                            // OnBackKeyPress canceled
                            taskScheduler.Canceled = true;
                            return;
                        }

                        if (taskScheduler.Canceled)
                        {
                            // go continue
                            taskScheduler.Canceled = false;
                            CancelOrContinueText = "取消";
                        }
                        else
                        {
                            // cancel
                            taskScheduler.Canceled = true;
                            CancelOrContinueText = "继续";
                        }
                    });
                }

                return cancelOrContinueCommand;
            }
        }

        #endregion

        #region properties

        string cancelOrContinueText;
        public string CancelOrContinueText
        {
            get { return cancelOrContinueText; }
            set
            {
                if (value != cancelOrContinueText)
                {
                    cancelOrContinueText = value;
                    NotifyPropertyChanged("CancelOrContinueText");
                }
            }
        }

        string tips;
        public string Tips
        {
            get { return tips; }
            set
            {
                if (value != tips)
                {
                    tips = value;
                    NotifyPropertyChanged("Tips");
                }
            }
        }

        SolidColorBrush tipsForeground;
        public SolidColorBrush TipsForeground
        {
            get { return tipsForeground; }
            set
            {
                if (value != tipsForeground)
                {
                    tipsForeground = value;
                    NotifyPropertyChanged("TipsForeground");
                }
            }
        }

        bool isIndeterminate;
        public bool IsIndeterminate
        {
            get { return isIndeterminate; }
            set
            {
                if (value != isIndeterminate)
                {
                    if (value)
                    {
                        ProgressVisibility = Visibility.Visible;
                    }
                    else
                    {
                        ProgressVisibility = Visibility.Collapsed;
                    }

                    isIndeterminate = value;
                    NotifyPropertyChanged("IsIndeterminate");
                }
            }
        }

        Visibility progressVisibility;
        public Visibility ProgressVisibility
        {
            get { return progressVisibility; }
            set
            {
                if (value != progressVisibility)
                {
                    progressVisibility = value;
                    NotifyPropertyChanged("ProgressVisibility");
                }
            }
        }

        #endregion

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
